// src/services/api.js - 基础API服务

// API基础URL
const API_BASE_URL = 'http://localhost:8080';

// API请求超时时间（毫秒）
const API_TIMEOUT = 5000;

// 默认请求头
const DEFAULT_HEADERS = {
  'Content-Type': 'application/json',
};

/**
 * 检查请求是否超时
 * @param {number} startTime - 请求开始时间
 * @returns {Promise} - 如果超时，返回一个被拒绝的Promise
 */
const checkTimeout = (startTime) => {
  if (Date.now() - startTime > API_TIMEOUT) {
    return Promise.reject(new Error('请求超时'));
  }
  return Promise.resolve();
};

/**
 * 添加身份验证令牌到请求头
 * @param {Object} headers - 请求头
 * @returns {Object} - 包含令牌的请求头
 */
const addAuthToken = (headers = {}) => {
  const token = localStorage.getItem('token');
  if (token) {
    return {
      ...headers,
      'Authorization': `${token}`
    };
  }
  return headers;
};

/**
 * 处理响应
 * @param {Response} response - fetch响应对象
 * @returns {Promise} - 解析后的响应数据
 */
const handleResponse = async (response) => {
  // 首先检查HTTP状态码
  if (!response.ok) {
    // 尝试解析错误信息
    try {
      const errorData = await response.json();
      const error = new Error(errorData.message || `请求失败: ${response.status}`);
      // 保留响应和错误数据以便访问状态码和详细信息
      error.response = response;
      error.status = response.status;
      error.data = errorData;
      throw error;
    } catch (e) {
      if (e.response) throw e; // 如果已经处理过，直接抛出
      const error = new Error(`请求失败: ${response.status}`);
      error.response = response;
      error.status = response.status;
      throw error;
    }
  }

  // 解析响应
  const data = await response.json();
  return data;
};

/**
 * 基础请求函数，包含重试逻辑
 * @param {string} endpoint - API端点
 * @param {Object} options - 请求选项
 * @param {number} retries - 重试次数
 * @returns {Promise} - 响应数据
 */
export const fetchWithRetry = async (endpoint, options = {}, retries = 2) => {
  const url = `${API_BASE_URL}${endpoint}`;
  const startTime = Date.now();

  try {
    await checkTimeout(startTime);

    const headers = options.headers || {};
    const authHeaders = options.auth !== false ? addAuthToken(headers) : headers;

    // 如果设置了skipDefaultHeaders，则不添加默认headers（用于文件上传）
    const finalHeaders = options.skipDefaultHeaders
      ? authHeaders
      : { ...DEFAULT_HEADERS, ...authHeaders };

    const response = await fetch(url, {
      ...options,
      headers: finalHeaders,
    });

    return await handleResponse(response);
  } catch (error) {
    // 如果是HTTP 4xx/5xx错误，不进行重试，直接抛出
    if (error.response) {
      throw error;
    }

    // 如果还有重试次数，并且是网络错误或超时，则尝试重试
    if (retries > 0) {
      console.warn(`请求失败，正在重试... (${retries}次重试剩余)`, error);
      // 指数退避，每次重试增加等待时间
      const delay = 1000 * (3 - retries);
      await new Promise(resolve => setTimeout(resolve, delay));
      return fetchWithRetry(endpoint, options, retries - 1);
    }

    // 记录请求失败
    console.error('API请求失败:', error);
    throw error;
  }
};

/**
 * GET请求
 * @param {string} endpoint - API端点
 * @param {Object} options - 请求选项
 * @returns {Promise} - 响应数据
 */
export const get = (endpoint, options = {}) => {
  return fetchWithRetry(endpoint, {
    ...options,
    method: 'GET',
  });
};

/**
 * POST请求
 * @param {string} endpoint - API端点
 * @param {Object} data - 请求体数据
 * @param {Object} options - 请求选项
 * @returns {Promise} - 响应数据
 */
export const post = (endpoint, data = {}, options = {}) => {
  return fetchWithRetry(endpoint, {
    ...options,
    method: 'POST',
    body: JSON.stringify(data),
  });
};

/**
 * PUT请求
 * @param {string} endpoint - API端点
 * @param {Object} data - 请求体数据
 * @param {Object} options - 请求选项
 * @returns {Promise} - 响应数据
 */
export const put = (endpoint, data = {}, options = {}) => {
  return fetchWithRetry(endpoint, {
    ...options,
    method: 'PUT',
    body: JSON.stringify(data),
  });
};

/**
 * DELETE请求
 * @param {string} endpoint - API端点
 * @param {Object} options - 请求选项
 * @returns {Promise} - 响应数据
 */
export const del = (endpoint, options = {}) => {
  return fetchWithRetry(endpoint, {
    ...options,
    method: 'DELETE',
  });
};

/**
 * 上传文件的POST请求
 * @param {string} endpoint - API端点
 * @param {FormData} formData - 表单数据
 * @param {Object} options - 请求选项
 * @returns {Promise} - 响应数据
 */
export const uploadFile = (endpoint, formData, options = {}) => {
  // 创建不包含Content-Type的headers，让浏览器自动设置multipart/form-data
  const authHeaders = addAuthToken();

  return fetchWithRetry(endpoint, {
    ...options,
    method: 'POST',
    body: formData,
    headers: authHeaders,
    // 设置特殊标记，让fetchWithRetry不添加DEFAULT_HEADERS
    skipDefaultHeaders: true,
  });
};

/**
 * 检查API是否可用
 * @returns {Promise<boolean>} - API是否可用
 */
export const isApiAvailable = async () => {
  try {
    // 尝试请求一个简单的端点
    await get('/health', { timeout: 2000 });
    return true;
  } catch (error) {
    console.warn('API不可用，将使用本地存储:', error);
    return false;
  }
};

export default {
  get,
  post,
  put,
  del,
  uploadFile,
  isApiAvailable,
}; 